﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace ReadAndWrite
{
    /// <summary>
    /// Cette classe de service permet de parser un fichier XML 
    /// mais aussi d'écrire dans un fichier XML.
    /// </summary>
    public class ReadAndWriteXML : ReadAndWrite
    {
        #region Attribut(s)

        /// <summary>
        /// Sérializeur pour lire ou écrire dans un fichier XML
        /// </summary>
        private XmlSerializer serializer;

        /// <summary>
        /// Type d'objet à sérialier ou désérialier
        /// </summary>
        private Type type;

        #endregion

        #region Propriété(s)


        #endregion

        #region Constructeur(s)

        /// <summary>
        /// Constructeur de classe prenant en paramètre le type d'objet du sérializeur (ex : typeof(Window) serait un type)
        /// et le chemin du fichier en lecture ou en écriture
        /// </summary>
        /// <param name="type">Type d'objet</param>
        /// <param name="path">Chemin du fichier</param>
        public ReadAndWriteXML(Type type, String path)
            : base(path)
        {
            serializer = new XmlSerializer(type);
            this.type = type;
        }

        #endregion

        #region Méthode(s)

        /// <summary>
        /// Sauvegarde dans un fichier XML sur le disque dur
        /// </summary>
        public void Save<T>(List<T> list)
        {
            if (VerifyType(list))
            {
                StreamWriter stream = new StreamWriter(Path, true);
                stream.AutoFlush = true;
                serializer.Serialize(stream, list);
                stream.Close();
            }
            else
            {
                throw new Exception(@"La liste d'objet passé en paramètre ne contient pas 
                que des types d'objets comme celui passé au constructeur");
            }
        }

        /// <summary>
        /// Sauvegarde dans un fichier XML sur le disque dur
        /// </summary>
        public void Save<T>(T obj)
        {
            StreamWriter stream = new StreamWriter(Path, true);
            stream.AutoFlush = true;
            serializer.Serialize(stream, obj);
            stream.Close();
        }

        /// <summary>
        /// Permet de vérifier si la liste passé en argument contient que des objets du type passé au constructeur
        /// </summary>
        /// <param name="list">Liste d'objet à sérialiser</param>
        /// <returns>Retourne si c'est ok ou non</returns>
        private bool VerifyType<T>(List<T> list)
        {
            foreach (object o in list)
            {
                if (o.GetType() != type)
                    return false;
            }

            return true;
        }

        /// <summary>
        /// Permet de charger un fichier XML et de retourner la liste d'objet.
        /// La liste d'objet est templétisé, c'est à dire qu'il faut spécifier à la méthode qu'elle sera le type d'un objet du fichier.
        /// Pour désérialiser un élément, il est obligatoire que la classe T possède un constructeur vide sinon le processus échouera.
        /// </summary>
        /// <typeparam name="T">Template d'un objet, cad la classe d'un élément du fichier</typeparam>
        /// <returns>Retourne la liste des objets présents dans le fichier XML</returns>
        public List<T> Load<T>()
        {
            List<T> listResult = new List<T>();

            if (File.Exists(Path))
            {
                StreamReader stream = new StreamReader(Path);

                try
                {
                    listResult = serializer.Deserialize(stream) as List<T>;
                }
                catch (InvalidOperationException) { }

                stream.Close();
            }

            return listResult;
        }

        #endregion
    }

}
